﻿using PLCS.Application.Contracts.HisTaskApp.Dtos;
using PLCS.Application.Contracts.PLCReadDataApp;
using PLCS.Application.Contracts.PLCReadDataApp.Dtos;
using PLCS.Domain.PLCConfigs;
using System.Diagnostics;
using System.Linq;
using Volo.Abp.Application.Dtos;

namespace PLCS.Application.PLCReadDataApp;

public class PLCReadDataAppService : CrudAppService<PLCReadData, PLCReadDataDto, Guid, PagedResultRequestDto, PLCReadDataEditDto>, IPLCReadDataAppService
{
    private readonly IPLCReadDataRepository _repository;
    private readonly IPLCConfigRepository _pLCConfigRepository;

    public PLCReadDataAppService(IPLCReadDataRepository repository, IPLCConfigRepository pLCConfigRepository) : base(repository)
    {
        _repository = repository;
        _pLCConfigRepository = pLCConfigRepository;
    }

    public async Task ChangeValueAsync(Guid Id, string value)
    {
        var readData = await _repository.GetAsync(Id);
        readData.ChangeValue(value);
        await _repository.UpdateAsync(readData);
    }

    public override async Task<PLCReadDataDto> CreateAsync(PLCReadDataEditDto input)
    {
        await CheckCreatePolicyAsync();

        var entity = await MapToEntityAsync(input);
        if (!string.IsNullOrWhiteSpace(input.PLCConfigNo))
        {
            var PLCConfig = await _pLCConfigRepository.FindAsync(x => x.PLCNo == input.PLCConfigNo);
            Check.NotNull(PLCConfig, input.PLCConfigNo);
            entity.PLCConfig = PLCConfig;
        }
        TryToSetTenantId(entity);

        await Repository.InsertAsync(entity, autoSave: true);

        return await MapToGetOutputDtoAsync(entity);
    }

    //public override async Task<PLCReadDataDto> CreateAsync(PLCReadDataEditDto input)
    //{
    //    var entity = ObjectMapper.Map<PLCReadDataEditDto, PLCReadData>(input);
    //    if (!string.IsNullOrWhiteSpace(input.PLCConfigNo))
    //    {
    //        var PLCConfig = await _pLCConfigRepository.FindAsync(x => x.PLCNo == input.PLCConfigNo);
    //        Check.NotNull(PLCConfig, input.PLCConfigNo);
    //        entity.PLCConfig = PLCConfig;
    //    }
    //    return await _repository.InsertAsync(entity);
    //}

    public async Task CreateListAsync(IEnumerable<PLCReadDataEditDto> inputs)
    {
        var stopwatch = Stopwatch.StartNew();
        Check.NotNull(inputs, "PLC字段集合");
        if (inputs.Count() == 0)
            throw new Exception("集合不能为空");
        var plcconfigs = await _pLCConfigRepository.GetListAsync();

        var entities = ObjectMapper.Map<IEnumerable<PLCReadDataEditDto>, IEnumerable<PLCReadData>>(inputs);
        foreach (var entity in entities)
        {
            var plcconfig = inputs.First(x => x.PLCReadDataNo == entity.PLCReadDataNo);
            var PLCConfig = plcconfigs.FirstOrDefault(x => x.PLCNo == plcconfig.PLCConfigNo);
            Check.NotNull(PLCConfig, plcconfig.PLCConfigNo);
            entity.PLCConfig = PLCConfig;
        }

        await _repository.InsertManyAsync(entities, autoSave: true);

        stopwatch.Stop();
        var elapsedSeconds = stopwatch.Elapsed.TotalSeconds;
        Console.WriteLine($"任务执行总时间：{elapsedSeconds}秒");
    }

    public async Task DeleteAllAsync()
    {
        var stopwatch = Stopwatch.StartNew();
        await _repository.DeleteAllAsync();
        stopwatch.Stop();
        var elapsedSeconds = stopwatch.Elapsed.TotalSeconds;
        Console.WriteLine($"任务执行总时间：{elapsedSeconds}秒");
    }

    public async Task<PLCReadDataDto> GetByNoAsync(string no)
    {
        var entity = await _repository.FindPLCReadDataByNoAsync(no);
        Check.NotNull(entity, no, $"PLC字段信息{no}不存在");
        return ObjectMapper.Map<PLCReadData, PLCReadDataDto>(entity);
    }

    [HttpPost]
    public async Task<IEnumerable<PLCReadDataDto>> GetListAsync()
    {
        var entities = await _repository.GetPLCReadDatasListAsync();
        var dtos = ObjectMapper.Map<IEnumerable<PLCReadData>, IEnumerable<PLCReadDataDto>>(entities);
        return dtos;
    }

    public async Task<PagedResultDto<PLCReadDataDto>> GetListBySearchAsync(PagedResultRequestDto input, Guid? plcConfigNo, string? startBit, string? deviceNo)
    {
        await CheckGetListPolicyAsync();

        var query = await CreateFilteredQueryAsync(input);
        query = query.Include(x => x.PLCConfig)
            .OrderBy(x => x.PLCConfigId).ThenBy(x => x.StartBit);
        bool isStartBit = int.TryParse(startBit, out int intStartBit);
        query = query.WhereIf(isStartBit, x => x.StartBit == intStartBit)
        .WhereIf(plcConfigNo != null && plcConfigNo != Guid.Empty, x => x.PLCConfigId == plcConfigNo)
        .WhereIf(!string.IsNullOrEmpty(deviceNo), x => x.PLCReadDataNo.Contains(deviceNo));

        var totalCount = await AsyncExecuter.CountAsync(query);

        query = ApplyPaging(query, input);

        var entities = await AsyncExecuter.ToListAsync(query);
        var entityDtos = await MapToGetListOutputDtosAsync(entities);

        return new PagedResultDto<PLCReadDataDto>(
            totalCount,
            entityDtos
        );
    }

    public async Task UpdateAsync(PLCReadDataEditDto input)
    {
        var entity = await GetEntityByIdAsync(input.Id);
        await MapToEntityAsync(input, entity);
        if (!string.IsNullOrWhiteSpace(input.PLCConfigNo))
        {
            var PLCConfig = await _pLCConfigRepository.FindAsync(x => x.PLCNo == input.PLCConfigNo);
            Check.NotNull(PLCConfig, input.PLCConfigNo);
            entity.PLCConfig = PLCConfig;
        }
        await Repository.UpdateAsync(entity, autoSave: true);
    }
}